package Lab3;

public class LinkedList<E> {
	private Node headOfList;
	private int itemCount;

	public LinkedList() {
		headOfList = null;
		itemCount = 0;
	}
	
	public void replace(int position, E what) {
		Node currItem = headOfList;
		
		for (int index = 0; index < position; index++) {
			currItem = currItem.nextOnList;
		}
		
		currItem.thingToStore = what;
	}
	
	public void addAll(LinkedList<E> otherList, int mark) {
		Node end = headOfList;
		
		while (end.nextOnList != null) {
			end = end.nextOnList;
		}
		
		copyChain(end, otherList);
	}
	
	private void copyChain(Node endOfList, LinkedList<E> listToCopy) {
		Node otherEnd = listToCopy.headOfList;
		
		while (otherEnd != null) {
			endOfList.nextOnList = otherEnd.nextOnList;
			itemCount++;
			otherEnd = otherEnd.nextOnList;
		}
	}
	
	public void addAll(LinkedList<E> otherList) {
		Node end = headOfList;
		Node otherEnd = otherList.headOfList;
		
		if (headOfList == null) {
			Node newBox = new Node(otherEnd.thingToStore);
			headOfList = newBox;
			itemCount++;
			end = headOfList;
			otherEnd = otherList.headOfList.nextOnList;
		}
		
		while (end.nextOnList != null) {
			end = end.nextOnList;
		}
		
		while (otherEnd != null) {
			Node newBox = new Node(otherEnd.thingToStore);
			end.nextOnList = newBox;
			itemCount++;
			end = end.nextOnList;
			otherEnd = otherEnd.nextOnList;
		}
	}
	
	public void add(E theObject) {
		Node newBox = new Node(theObject);

		if (headOfList == null) {
			headOfList = newBox;
			itemCount++;
			return;
		}

		Node end = headOfList;
		while (end.nextOnList != null) {
			end = end.nextOnList;
		}

		end.nextOnList = newBox;

		itemCount++;
	}

	public E getPosition(int position) {
		if (position > itemCount - 1) {
			return null;
		}

		Node currentLink = headOfList;

		for (int index = 0; index < position; index++) {
			currentLink = currentLink.nextOnList;
		}

		return currentLink.thingToStore;
	}

	public int size() {
		return itemCount;
	}

	public void remove(int whichPosition) {
		if (whichPosition == 0) {
			headOfList = headOfList.nextOnList;
			itemCount--;
			return;
		}

		// Advance to the element just before the one we want to delete

		Node theOneBefore = headOfList;

		for (int index = 0; index < whichPosition - 1; index++) {
			theOneBefore = theOneBefore.nextOnList;
		}

		Node theOneToRemove = theOneBefore.nextOnList;
		Node theOneAfter = theOneToRemove.nextOnList;
		theOneBefore.nextOnList = theOneAfter;

		itemCount--;
	}

	@Override
	public String toString() {
		String contents = "";

		if (headOfList == null) {
			return "null";
		}

		Node currentLink = headOfList;

		for (int index = 0; index < itemCount; index++) {
			contents = contents + "[ " + currentLink.toString() + "] ";
			currentLink = currentLink.nextOnList;
		}

		return contents;
	}

	private class Node {
		E thingToStore;
		Node nextOnList;

		Node(E thingToStore) {
			this.thingToStore = thingToStore;
		}

		@Override
		public String toString() {
			return thingToStore.toString();
		}
	}
}